#pragma once
#include <vulkan/vulkan_raii.hpp>
#include <GLFW/glfw3.h>
#include <span>
#include <vector>
#include <optional>
namespace Lumine
{
    struct QueueFamilyIndices
    {
        std::optional<uint32_t> graphicsFamily;
        std::optional<uint32_t> presentFamily;
        std::optional<uint32_t> transferFamily;

        bool isComplete()
        {
            return graphicsFamily.has_value() &&
                   presentFamily.has_value() &&
                   transferFamily.has_value();
        }
    };

    class LumineContext
    {
    private:
        LumineContext() = default;
        ~LumineContext() = default;
        LumineContext(const LumineContext &) = delete;
        LumineContext &operator=(const LumineContext &) = delete;
        //===========================================================
        //                      部分常量
        //===========================================================
        // 实例级层
        std::vector<const char *> instanceLayers = {
            "VK_LAYER_KHRONOS_validation"};

        std::vector<const char *> deviceExtensions = {
            vk::KHRSwapchainExtensionName,
            vk::KHRSpirv14ExtensionName,
            vk::KHRCreateRenderpass2ExtensionName,
            vk::KHRShaderDrawParametersExtensionName};

        //===========================================================
        //                      核心RAII资源成员
        //===========================================================
        vk::raii::Context m_context;
        vk::raii::Instance m_instance = nullptr;
        vk::raii::DebugUtilsMessengerEXT m_debugMessenger = nullptr;
        vk::raii::SurfaceKHR m_surface = nullptr;

        vk::raii::PhysicalDevice m_physicalDevice = nullptr;
        vk::raii::Device m_device = nullptr;
        // 队列和索引
        uint32_t graphicIndex = 0;
        uint32_t presentIndex = 0;
        uint32_t transferIndex = 0;
        vk::Queue m_graphicQueue = nullptr;
        vk::Queue m_presentQueue = nullptr;
        vk::Queue m_transferQueue = nullptr;
        QueueFamilyIndices indices;

        //===========================================================
        //                      内部初始化辅助方法
        //===========================================================
        std::vector<const char *> getRequiredInstanceExtensions();

        void findQueueFamilies();

        void pickPhysicalDevice();

        void createInstance();

        /// @brief 为Vulkan创建Debug工具
        void setupDebugMessenger();

        void createSurface(GLFWwindow *m_window);

        void createLogicDevice();

        vk::Result checkInstanceLayers(std::span<const char *> layerToCheck);

        vk::Result checkInstanceExtensions(std::span<const char *> extensionToCheck, const char *layerName = nullptr);

        static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT severity, vk::DebugUtilsMessageTypeFlagsEXT type, const vk::DebugUtilsMessengerCallbackDataEXT *pCallbackData, void *);

    public:
        //===========================================================
        //                      静态访问点
        //===========================================================
        static LumineContext &Get()
        {
            static LumineContext instance;
            return instance;
        }

        //===========================================================
        //                      初始化公共API
        //===========================================================
        void InitializeInstance(GLFWwindow *window);
        void InitializeDevice();

        //===========================================================
        //                  核心资源的公共访问器
        //===========================================================
        const vk::raii::Instance &GetInstance() const { return m_instance; }
        const vk::raii::Device &Device() const { return m_device; }
        const vk::raii::PhysicalDevice &PhysicalDevice() const { return m_physicalDevice; }
        const vk::raii::SurfaceKHR &Surface() const { return m_surface; }

        // 提供对队列和索引的访问
        // const QueueFamilyIndices &QueueFamilyIndices() const { return m_queueFamilyIndices; }
        const uint32_t GraphicIndex() const { return indices.graphicsFamily.value(); }
        const uint32_t PresentIndex() const { return indices.presentFamily.value(); }
        const uint32_t TransferIndex() const { return indices.transferFamily.value(); }
        const vk::Queue &GraphicQueue() const { return m_graphicQueue; }
        const vk::Queue &PresentQueue() const { return m_presentQueue; }
        const vk::Queue &TransferQueue() const { return m_transferQueue; }
    };
}